home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
To access the contents, click the chapter and section titles.

Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
(Publisher: John Wiley & Sons, Inc.)
Author(s): Rod Stephens
ISBN: 0471323519
Publication Date: 11/01/98

Search this book:
 
Previous Table of Contents Next


Underflow errors are easy to overlook. You must be sure you consider variables with both large positive and negative values.

If it is easy to determine what parameter values will produce errors, use Debug.Assert or Stop statements to verify that the values are acceptable. Use an On Error statement to catch the error in more complicated situations and in the compiled version of the program.

Function DoubleIt(ByVal x As Integer) As Integer
    Debug.Assert (x >= -16384) And (x <= 16383)

    DoubleIt = 2 * x
End Function

Watch for Divide by 0

Watch for expressions that could cause a divide-by-0 error. If an expression includes division, check the denominator to see if can ever be 0. Use Debug.Assert, Stop, and On Error statements to prevent the routine from crashing.

Function Invert(ByVal x As Integer) As Integer
    Debug.Assert x <> 0

    Invert = 1 \ x
End Function

Be Aware of Argument Promotion

Be certain you understand how the types of variables change when they are passed to routines or used in expressions. Use parentheses and data type conversion functions to force Visual Basic to handle the values as you intend.

Think about how variable promotion can interact with the other guidelines discussed in this chapter. For example, after the following code runs, it looks as if x and y should have the same value. However, when the program reaches the statement y = 0#, Visual Basic promotes y to the double data type. During the For loop, y retains more precision than x, which is only a single. At the end of the loop, x has the value 9.999999 while y has the value 10.0000004172325. These values are not exactly equal, so the message box never appears.

Private Sub PromotionProblem()
Dim x As Single
Dim y As Variant
Dim dx As Single
Dim i As Integer

    dx = 10 / 17
    y = 0#
    x = y
    For i = 1 To 17
        ‘ Do something with x and y.

        x = x + dx
        y = y + dx
    Next i

    If x = y Then MsgBox “The values are equal.”
End Sub

Do not rely on Visual Basic to behave as you expect. Make the results of expressions obvious to developers who read the code later.

Avoid Error Codes

The problem with functions that return error codes is that you must remember to check them. If a routine returns an error code and the program ignores it, you will not be aware that a problem may be occurring. On the other hand, if a routine raises an error, you cannot fail to notice it. You must trap the error with an On Error statement or the program will crash.

Try to use routines that always work. You do not need to handle errors that cannot arise. If you cannot use an error-proof routine, use one that raises errors when it fails instead of returning a status code.

If neither of those options is available, be certain you check the function’s status code. Visual Basic allows a program to treat a function as if it were a procedure if the program does not want the function’s return value. For example, the LineTo API function draws a line to a specified point and returns a nonzero value if it is successful. The following code shows how a program can invoke LineTo with and without the return code.

Private Declare Function LineTo Lib “gdi32” Alias “LineTo” _
    (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
         :
Private Sub DrawLines()
Dim status As Long

    ‘ Treat as a subroutine, ignoring the return code.
    LineTo hdc, 100, 200

    ‘ Check the return code.
    status = LineTo(hdc, 200, 300)
    Debug.Assert (status <> 0)
End Sub

If you use a function that returns a status code, do not ignore the code. See if the routine succeeded and take appropriate action if it did not.

Don’t Assume Variable Sizes

Do not assume variable sizes will remain the same forever. For example, do not assume integers take 4 bytes and that doubles take 8. Those values probably will not change in the near future, but stranger things have happened. At some point in the future, when most computers use 128-bit addressing, doubles could change to 16 or 32 bytes. Use the Len and LenB functions to see how large variables are if you need to know.

Don’t Assume Constant Values

Do not assume constant values defined by Visual Basic will never change. In particular, do not assume that True will always have the value –1. False is likely to remain 0, but the value of True has been redefined by other languages like Pascal in the past. It could happen in Visual Basic.

If you need to assign the value 0 or –1 to a variable depending on the results of a Boolean expression, use an If statement, not a simple assignment.

Dim X As Integer

    X = (A = B)      ‘ Don‘t use this method.

    If (A = B) Then  ‘ Use this method instead.

        X = -1
    Else
        X = 0
    End If

Self-Test

Program Bad8 violates several of the guidelines presented in this chapter. The program, shown in Figure 8.1, presents a sorted list of numbers. Enter a number and click the Search button to make the program try to find the number in the list.


Figure 8.1  Program Bad8 failing to locate the number 24.307.

Unfortunately, program Bad8 practically never finds the correct number. In fact, it does not even correctly generate a sorted list. Some of the numbers are not in sorted order. If the program obeyed all of the guidelines described in this chapter, it would not have these problems.

Option Explicit

‘ The list of values.
Private Const NUM_VALUES = 50
Private Values(1 To NUM_VALUES) As Variant

‘ Initialize the data.
Private Sub Form_Load()
    InitializeData
End Sub

‘ Create some random data.
Private Sub InitializeData()
Dim i As Integer
Dim last_value As Integer     ‘ The last value assigned.
Dim txt As String

    Randomize

    ‘ Initialize the random numbers with each
    ‘ value slightly bigger than the previous one.
    last_value = 10
    For i = 1 To NUM_VALUES
        Values(i) = last_value + Rnd + 0.01
        last_value = Values(i)
    Next i

    ‘ Display the values.
    For i = 1 To NUM_VALUES
        txt = txt & Format$(i, “@@”) & “: ” & _
            Format$(Values(i), “0.000”) & vbCrLf
    Next i
    txtValues.Text = txt
End Sub

‘ Search for the target.
Private Sub CmdSearch_Click()
Dim position As Integer

    position = LinearSearch(Values, txtTarget.Text)
    If position < 1 Then
        lblPosition.Caption = “Not found”
    Else

        lblPosition.Caption = Format$(position)
    End If
End Sub

‘ Locate a target item using linear search. If the
‘ target is not found, return 1 less than the
‘ smallest array index.
Public Function LinearSearch(list() As Variant, _
    target As Variant) As Integer
Dim i As Integer

    For i = LBound(list) To UBound(list)
        ‘ See if we found the target.
        If list(i) = target Then
            LinearSearch = i
            Exit Function
        End If

        ‘ If the values are too big, we passed
        ‘ where it should be so it’s not here.
        If list(i) > target Then Exit For
    Next i
End Function


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.